package com.qyoung.designPattern.singleton;

import com.qyoung.designPattern.entity.Student;

/**
 *  单例模式之懒汉式：等到需要用的时候在创建
 *  线程安全版：
 *  使用 volatile 修饰是因为创建 Student 对象在字节码层面可大致分为以下三个步骤：
 *      1、new 在堆中为对象申请相应的空间
 *      2、对对象的成员变量进行默认值的初始化，比如 int 类型的成员变量默认值为 0
 *      3、将栈中的局部变量对象的引用指向堆的地址
 *  实际上 JVM 在字节码的编译期间会根据实际情况对指令进行优化，也就是会做指令重排（对应操作系统的指令流水线），
 *  此时如果步骤 2，和步骤 3 发生了指令重排，恰好该线程时间片到，另一线程过来拿到的就是一个半成品的对象。
 */
public class SingletonLazy {

    private static volatile Student student = null;

    // 构造函数私有化
    private SingletonLazy() {}

    public static Student getInstance() {
        // 双重检查锁，
        if (student == null) {
            synchronized (SingletonLazy.class) {
                if (student == null) {
                    student = new Student();
                }
            }
        }
        return student;
    }

}
